
#include "processmgr.h"
#include "time.h"
#include "frame_interface.h"
#include <xercesc/dom/DOM.hpp>
#include <xercesc/sax/HandlerBase.hpp>
#include <fstream>
#include <unistd.h>
#include <stdarg.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>

#define PCC_FLOW_ID	99999

//NAMESPACE_BILLING40_FRAME CProcessMgr NAMESPACE_BILLING40_FRAME *g_pProcessMgr = NULL;
NAMESPACE_BILLING40_FRAME CProcessMgr *g_pProcessMgr = NULL;

int32 NAMESPACE_BILLING40_FRAME CProcessMgr::m_iSignal = 0;
int32 NAMESPACE_BILLING40_FRAME CProcessMgr::m_iRet = RET_OK;

int32 NAMESPACE_BILLING40_FRAME CProcessMgr::start(const char *cszConfigFile,
	const char *cszProgram,
	const bool& bSetDaemon)
{
	CTimeMgr::fill_time(&g_objTime);
	g_pTime = &g_objTime;

	m_tid = pthread_self();

	//read log config
	strcpy(m_objConfig.m_szConfigFileName, cszConfigFile);
	int32 iRet = m_objXmlFile.read_config((CFrameLogConfig&)m_objConfig,
		m_objConfig.m_szConfigFileName,
		m_pLog);
	if(iRet!=0) return iRet;

	//init system log
	if(m_pLog!=NULL)
	{
		delete m_pLog;
		m_pLog=NULL;
	}
	
	char szErrMsg[1024];
	strcpy(m_objConfig.m_objCommonConfig.m_objLog.m_szModuleName, "system");
	
	m_pLog = NAMESPACE_BILLING40_LOG CLog::init_log(
		szErrMsg,
		m_objConfig.m_objCommonConfig.m_objLog);	
	if(m_pLog==NULL)
	{
		printf(szErrMsg);
		return -1;
	}

	if(bSetDaemon)
	{
		iRet = set_daemon();
		if(iRet != 0) return -1;
	}

	LogInit(m_pLog);

//	iRet = redirect_stdio();
//	if(iRet!=0) return -1;

	m_iPid = getpid();
	m_iProcId = m_objConfig.m_objCommonConfig.m_iProcId;
	m_iCpfFlowId = m_objConfig.m_objCommonConfig.m_iCpfFlowId;
	m_iCpfServiceId = m_objConfig.m_objCommonConfig.m_iCpfServiceId;
	m_iCpfProcId = m_objConfig.m_objCommonConfig.m_iCpfProcId;

	iRet = check_config();
	if(iRet!=0) return iRet;

	iRet = m_objXmlFile.read_config(m_objConfig, m_objConfig.m_szConfigFileName, m_pLog);
	if(iRet!=0) return iRet;

	CThreadObj::pthread_attrInit();

	//start clock
	m_objClock.m_arrFunction.push_back(CNodeDef::CFunction());
	m_objClock.m_arrFunction.begin()->m_createInstanceFunc = create_clockInstance;
	m_objClock.m_bHeadNode = true;
	m_objClock.m_bTailNode = true;
	CFrameConfig::CFlowConfig::CNodeConfig objNodeConfig;
	strcpy(objNodeConfig.m_szNodeName, "clock");
	m_objSysFlow.m_pLog = m_pLog;
	m_objClock.m_pFlow = &m_objSysFlow;
	NAMESPACE_BILLING40_XML_CONFIG CDOMNodeList lstFlowConfig;
	m_objClock.update_config(objNodeConfig, lstFlowConfig, true);
	m_objClock.run();

	/*****
	//init timer
	m_objTimer.m_arrFunction.push_back(CNodeDef::CFunction());
	m_objTimer.m_arrFunction.begin()->m_createInstanceFunc = create_timerInstnace;
	m_objTimer.m_bHeadNode = true;
	m_objTimer.m_bTailNode = true;
	strcpy(objNodeConfig.m_szNodeName, "timer");
	m_objTimer.m_pFlow = &m_objSysFlow;
	m_objTimer.update_config(objNodeConfig, lstFlowConfig, true);
	*****/

	//200908zhongyf
	iRet = m_objXmlFile2.read_config(m_objCommonNodeConfig, m_objConfig.m_szConfigFileName, m_pLog);
        if(iRet!=0) return iRet;
	
	m_objManageLock.lock();
	iRet = check_process(cszProgram);
	//sleep(30);		//for debug use
	if(iRet==0)
	{
		iRet = update_config();
	}
	m_objManageLock.unlock();

	if(iRet != 0) return -1;

	//run timer
	//m_objTimer.run();

	return 0;
}

int32 NAMESPACE_BILLING40_FRAME CProcessMgr::stop()
{
	m_objManageLock.lock();
	for(FlowMap::iterator itFlow=m_mapFlow.begin();
		itFlow!=m_mapFlow.end();++itFlow)
	{
		// stop all flows, except pcc flow
		if (!(itFlow->second->m_iFlowId == PCC_FLOW_ID || strncmp(itFlow->second->m_szFlowName, "pcc", 4) == 0))
			delete itFlow->second;
	}
	for(FlowMap::iterator itFlow=m_mapFlow.begin();
		itFlow!=m_mapFlow.end();++itFlow)
	{
		// stop pcc flow
		if (itFlow->second->m_iFlowId == PCC_FLOW_ID || strncmp(itFlow->second->m_szFlowName, "pcc", 4) == 0)
			delete itFlow->second;
	}

	//m_objTimer.stop();
	//m_objTimer.destroy();
	m_objClock.stop();
	m_objClock.destroy();
	m_objManageLock.unlock();

	CThreadObj::pthread_attrDestroy();

	m_iSendLogLevel = FATAL_LEVEL+1;

	remove_pidFile();

	LogAppend(NAMESPACE_BILLING40_LOG WARN_LEVEL, "program exit successfully!");

	LogEnd();
	if(m_pLog!=NULL)
	{
		delete m_pLog;
		m_pLog=NULL;
	}

	return 0;
}

int32 NAMESPACE_BILLING40_FRAME CProcessMgr::manage()
{
	CControlPkg *pControlPkg = NULL;
	int32 iRet = 0;

	m_objManageLock.lock();

	if(m_pProcessMessage != NULL)
	{
		pControlPkg = m_pProcessMessage->receive_message();
		if(pControlPkg != NULL)
		{ 
			control(*pControlPkg);

			delete pControlPkg;
			pControlPkg = NULL;
		}
	}
	
	m_tSleepTime = MAX_SLEEP_TIME;
	time_t tCheckTime = MAX_SLEEP_TIME;
	for(FlowMap::iterator itFlow=m_mapFlow.begin();
		itFlow!=m_mapFlow.end();++itFlow)
	{
		tCheckTime = itFlow->second->check_action();
		m_tSleepTime = m_tSleepTime < tCheckTime ? m_tSleepTime : tCheckTime;
		if(g_pTime->m_tmVal.tv_sec>m_lLastManageTime+MAX_SLEEP_TIME)
		{
			iRet = itFlow->second->manage();
		}
		if(iRet != 0) break;
		//add by dengyong for refresh config
		//itFlow->second->refresh_config();
	}
	if(g_pTime->m_tmVal.tv_sec>m_lLastManageTime+MAX_SLEEP_TIME)
	{
		m_lLastManageTime = g_pTime->m_tmVal.tv_sec;
	}
	m_objManageLock.unlock();

	bool bIsAllBusinessFlowStoped = true;
	m_objManageLock.lock();
	for(FlowMap::iterator itFlow=m_mapFlow.begin();
		itFlow!=m_mapFlow.end();++itFlow)
	{
		if(itFlow->second->m_eStat != CFlow::STOP
			&& itFlow->second->m_eFlowType == CFrameConfig::CFlowConfig::FLOW_TYPE_BUSINESS)
		{
			bIsAllBusinessFlowStoped = false;
			break;
		}
	}
	m_objManageLock.unlock();
	
	if(bIsAllBusinessFlowStoped)
	{
		if (CProcessMgr::m_iRet == RET_FINISH) {
			CControlPkg * pkg = new CControlPkg();
	        pkg->m_iMsgType = 3025;
	        pkg->m_strMsgInfo = "";
	        send_message(pkg);
		}

		LogAppend(NAMESPACE_BILLING40_LOG FATAL_LEVEL,
			"all business flow stoped, program will exit");
		kill(getpid(), SIGTERM);
	}
        
        sleep(m_tSleepTime);
	return 0;
}

int32 NAMESPACE_BILLING40_FRAME CProcessMgr::check_config()
{
	int32 iRet = 0;
	CFrameConfig *pConfig = new CFrameConfig();

	iRet = m_objXmlFile.read_config(*pConfig, m_objConfig.m_szConfigFileName, m_pLog);
	if(iRet!=0)
	{
		delete pConfig;
		return -1;
	}

	iRet = m_objFunction.check_config(pConfig->m_lstFuncDefineConfig);
	if(iRet!=0)
	{
		delete pConfig;
		return -1;
	}

	iRet = m_mapNodeDefine.check_config(*pConfig);
	if(iRet!=0)
	{
		delete pConfig;
		return -1;
	}

	typedef AISTD set< int32 > IndexSet;
	IndexSet setIndexNodeDef;
	for(CFrameConfig::NodeDefineConfigList::iterator itNodeDefConf=pConfig->m_lstNodeDefineConfig.begin();
		itNodeDefConf!=pConfig->m_lstNodeDefineConfig.end();++itNodeDefConf)
	{
		setIndexNodeDef.insert(itNodeDefConf->m_iNodeDefId);
	}
	IndexSet setIndexFlow;
	for(CFrameConfig::FlowConfigList::iterator itFlowConf=pConfig->m_lstFlowConfig.begin();
		itFlowConf!=pConfig->m_lstFlowConfig.end();++itFlowConf)
	{
		if(itFlowConf->m_iFlowId<=0)
		{
			LogAppend(NAMESPACE_BILLING40_LOG FATAL_LEVEL,
				"flow_id:%d must be greater than 0",
				itFlowConf->m_iFlowId);
			delete pConfig;
			return -1;
		}
		IndexSet::iterator itIndexFlow=setIndexFlow.find(itFlowConf->m_iFlowId);
		if(itIndexFlow==setIndexFlow.end())
		{
			setIndexFlow.insert(itFlowConf->m_iFlowId);
		}
		else
		{
			LogAppend(NAMESPACE_BILLING40_LOG FATAL_LEVEL,
				"redeclaration of flow_id:%d",
				itFlowConf->m_iFlowId);
			delete pConfig;
			return -1;
		}
		if(itFlowConf->m_lstNodeConfig.empty())
		{
			LogAppend(NAMESPACE_BILLING40_LOG FATAL_LEVEL,
				"no node define in flow flow_id:%d",
				itFlowConf->m_iFlowId);
			delete pConfig;
			return -1;
		}
		IndexSet setIndexNode;
		for(CFrameConfig::CFlowConfig::NodeConfigList::iterator itNodeConf=itFlowConf->m_lstNodeConfig.begin();
			itNodeConf!=itFlowConf->m_lstNodeConfig.end();++itNodeConf)
		{
			IndexSet::iterator itNode = setIndexNode.find(itNodeConf->m_iNodeId);
			if(itNode==setIndexNode.end())
			{
				setIndexNode.insert(itNodeConf->m_iNodeId);
			}
			else
			{
				LogAppend(NAMESPACE_BILLING40_LOG FATAL_LEVEL,
					"redeclaration of node_id:%d in flow_id:%d",
					itNodeConf->m_iNodeId,
					itFlowConf->m_iFlowId);
				delete pConfig;
				return -1;
			}
		}
		for(CFrameConfig::CFlowConfig::NodeConfigList::iterator itNodeConf=itFlowConf->m_lstNodeConfig.begin();
			itNodeConf!=itFlowConf->m_lstNodeConfig.end();++itNodeConf)
		{
			IndexSet::iterator itNodeDef = setIndexNodeDef.find(itNodeConf->m_iDefineNodeId);
			if(itNodeDef==setIndexNodeDef.end())
			{
				LogAppend(NAMESPACE_BILLING40_LOG FATAL_LEVEL,
					"node_define_id:%d used in flow_id:%d node_id:%d not defined in node define",
					itNodeConf->m_iDefineNodeId,
					itFlowConf->m_iFlowId,
					itNodeConf->m_iNodeId);
				delete pConfig;
				return -1;
			}
			CFrameConfig::CFlowConfig::CNodeConfig::NextNodeList::iterator itNextNode;
			for(itNextNode=itNodeConf->m_lstNextNode.begin();
				itNextNode!=itNodeConf->m_lstNextNode.end();++itNextNode)
			{
				IndexSet::iterator itNode = setIndexNode.find(itNextNode->m_iNextNodeId);
				if(itNode==setIndexNode.end())
				{
					LogAppend(NAMESPACE_BILLING40_LOG FATAL_LEVEL,
						"the next node_id:%d used in flow_id:%d node_id:%d not defined in the flow",
						itNextNode->m_iNextNodeId,
						itFlowConf->m_iFlowId,
						itNodeConf->m_iNodeId);
					delete pConfig;
					return -1;
				}
				if(itNextNode->m_iNextNodeIndex>=CNode::NODE_LIST_SIZE)
				{
					LogAppend(NAMESPACE_BILLING40_LOG FATAL_LEVEL,
						"the next node index %d in %d/%d must between 0~%d ", 
						itNextNode->m_iNextNodeIndex,
						itFlowConf->m_iFlowId,
						itNodeConf->m_iNodeId,
						CNode::NODE_LIST_SIZE-1);
					delete pConfig;
					return -1;
				}
			}
		}
	}

	delete pConfig;
	return 0;
}

int32 NAMESPACE_BILLING40_FRAME CProcessMgr::update_config()
{
	int32 iRet = 0;

	char szErrMsg[1024];
	NAMESPACE_BILLING40_LOG CLog *pLog = NAMESPACE_BILLING40_LOG CLog::init_log(
		szErrMsg,
		m_objConfig.m_objCommonConfig.m_objLog,
		m_pLog);
	if(pLog==NULL)
	{
		LogAppend(NAMESPACE_BILLING40_LOG FATAL_LEVEL, szErrMsg);
		return -1;
	}

	iRet = m_objFunction.update_config(m_objConfig);
	if(iRet != 0)
	{
		send_startProcess(m_iPid, iRet);
		return -1;
	}

	//update node define
	iRet = m_mapNodeDefine.update_config(m_objConfig.m_lstNodeDefineConfig);
	if(iRet != 0)
	{
		send_startProcess(m_iPid, iRet);
		return -1;
	}

	//update flow
	//delete flow not configed
	for(FlowMap::iterator itFlow=m_mapFlow.begin();
		itFlow!=m_mapFlow.end();)
	{
		bool bFoundConf = false;
		for(CFrameConfig::FlowConfigList::iterator itFlowConf=m_objConfig.m_lstFlowConfig.begin();
			itFlowConf!=m_objConfig.m_lstFlowConfig.end();++itFlowConf)
		{
			if(itFlow->first!=itFlowConf->m_iFlowId) continue;
			bFoundConf = true;
			break;
		}
		CFlow *pFlow = itFlow->second;
		FlowMap::iterator itTmpFlow = itFlow;
		++itFlow;
		if(bFoundConf) continue;
		if(itFlow==m_mapFlow.end())
		{
			m_mapFlow.erase(itTmpFlow);
			itFlow = m_mapFlow.end();
		}
		else
		{
			m_mapFlow.erase(itTmpFlow);
		}
		delete pFlow;
	}
		
	//update/add flow
	for(CFrameConfig::FlowConfigList::iterator itFlowConf=m_objConfig.m_lstFlowConfig.begin();
		itFlowConf!=m_objConfig.m_lstFlowConfig.end();++itFlowConf)
	{
		FlowMap::iterator itFlow = m_mapFlow.find(itFlowConf->m_iFlowId);
		if(itFlow==m_mapFlow.end())
		{
			CFlow *pFlow = new CFlow(itFlowConf->m_iFlowId);
			itFlow = m_mapFlow.insert(m_mapFlow.end(),
				FlowMap::value_type(itFlowConf->m_iFlowId, pFlow));
		}
		
		//200908zhongyf
		iRet = itFlow->second->update_config(*itFlowConf,m_objCommonNodeConfig.m_lstCommonConfigsDOMNode); 
		if(iRet != 0)
		{
			send_startProcess(m_iPid, iRet);
			return -1;
		}
	}

	send_startProcess(m_iPid, 0);

	return 0;
}

int32 NAMESPACE_BILLING40_FRAME CProcessMgr::control(CControlPkg& controlPkg)
{
	for(FlowMap::iterator itFlow = m_mapFlow.begin();
		itFlow != m_mapFlow.end(); ++itFlow)
	{
		int32 iRet = itFlow->second->control(controlPkg);
		if(iRet != 0) return iRet;
	}
	
	return 0;
}

int32 NAMESPACE_BILLING40_FRAME CProcessMgr::send_message(CControlPkg *pControlPkg)
{
	if(pControlPkg == NULL) return 0;
	
	m_objMessageLock.lock();
	if(m_pProcessMessage != NULL)
	{
		m_pProcessMessage->send_message(pControlPkg);
	}
	else
	{
		delete pControlPkg;
		pControlPkg = NULL;
	}
	m_objMessageLock.unlock();

	return 0;
}

void NAMESPACE_BILLING40_FRAME CProcessMgr::set_messageObj(IProcessMessage *pProcessMessage)
{
	m_objMessageLock.lock();
	m_pProcessMessage = pProcessMessage;
	m_objMessageLock.unlock();
}

void NAMESPACE_BILLING40_FRAME CProcessMgr::clear_messageObj(IProcessMessage *pProcessMessage)
{
	m_objMessageLock.lock();
	if(m_pProcessMessage == pProcessMessage)
	{
		m_pProcessMessage = NULL;
	}
	m_objMessageLock.unlock();
}

//UNDO...
/*********************************
void NAMESPACE_BILLING40_FRAME CProcessMgr::send_stopProgress(int32 iProgress)
{
	iProgress = m_iStoppedPipeLineCount * 1000000 + iProgress;
	iProgress /= (m_mapPipeLine.size() <= 1 ? 1 : m_mapPipeLine.size() - 1);

	LogAppend(NAMESPACE_BILLING40_LOG DEBUG_LEVEL, 
		"pipe line count %d, stop pip line %d",
		m_mapPipeLine.size(), m_iStoppedPipeLineCount);

	if(iProgress >= 1000000)
	{
		LogAppend(NAMESPACE_BILLING40_LOG DEBUG_LEVEL, 
			"pipe line count %d, stop pip line %d _",
			m_mapPipeLine.size(), m_iStoppedPipeLineCount);

		iProgress = 1000000;
		if(m_mapPipeLine.size() - m_iStoppedPipeLineCount >1)
		iProgress -=1;
		UnlockPidFile();
	}

	LogAppend(NAMESPACE_BILLING40_LOG DEBUG_LEVEL, "CProcessMgr stopProgress %d", iProgress);

	if(this->m_pProcessMessage)
	{
		m_objManageLock.lock();
		this->m_pProcessMessage->send_stopProgress(iProgress);
		m_objManageLock.unlock();
	}
}
*********************************/

void NAMESPACE_BILLING40_FRAME CProcessMgr::send_startProcess(int32 iPid, int32 iResult)
{
	LogAppend(NAMESPACE_BILLING40_LOG DEBUG_LEVEL, "CProcessMgr startProcess Pid: %d, iResult: %d", iPid, iResult);

	if(this->m_pProcessMessage)
	{
		LogAppend(NAMESPACE_BILLING40_LOG DEBUG_LEVEL, "Before send start message!");

		//m_objManageLock.lock();
                // In Ecframe, iResult == 0 means success, but in PCC, iResult == 1 means success, so need convert
                this->m_pProcessMessage->send_startProcess(iPid, (iResult == 0));
		//m_objManageLock.unlock();

		LogAppend(NAMESPACE_BILLING40_LOG DEBUG_LEVEL, "After send start message!");
	}
}

int32 NAMESPACE_BILLING40_FRAME CProcessMgr::check_process(const char *cszProgram)
{
	int32 iRet = 0;
	iRet = check_dir(m_objConfig.m_objCommonConfig.m_objLog.m_szPath);
	if(iRet!=0) return -1;

	char szHostName[128];
	gethostname(szHostName, 128);

	char szFile[1024];
	sprintf(szFile,
		"%s/pid_%d_%s",
		m_objConfig.m_objCommonConfig.m_objLog.m_szPath,
		m_objConfig.m_objCommonConfig.m_iProcId,
		szHostName);
	pid_t iPid = 0;
	char szOldHostName[128];
	{
		AISTD ifstream ifPid(szFile);
		ifPid >> iPid;
	}

	if(iPid>0)
	{
		char szBuf[256];
		const char *cszPos = NULL;
		cszPos = strrchr(cszProgram, '/');
		cszPos = cszPos==NULL ? cszProgram : cszPos+1;
		sprintf(szBuf,
			"ps -ef | grep %d | grep %s | grep -v \"grep %d\" | wc -l",
			iPid,
			cszPos,
			iPid);
		LogAppend(NAMESPACE_BILLING40_LOG DEBUG_LEVEL,
			"exec shell %s ",
			szBuf);
		FILE *pFile = NULL;
		while(true)
		{
			pFile = popen(szBuf, "r");
			if(pFile == NULL) continue;
			cszPos = fgets(szBuf, sizeof(szBuf), pFile);
			pclose(pFile);
			if(cszPos==szBuf) break;
		}
		LogAppend(NAMESPACE_BILLING40_LOG DEBUG_LEVEL,
			"shell result %s",
			szBuf);
		if(atoi(szBuf)>0)
		{
			LogAppend(NAMESPACE_BILLING40_LOG FATAL_LEVEL,
				"make sure the program is not in running, remove file %s and try again",
				szFile);
			return -1;
		}
	}
	iPid = getpid();
	AISTD ofstream ofPid(szFile);
	ofPid << iPid;
	return 0;
}
int32 NAMESPACE_BILLING40_FRAME CProcessMgr::check_dir(const char *cszDir)
{
	if(cszDir==NULL) return 0;
	if(*cszDir=='\0') return 0;
	struct stat statbuf;
	if(stat(cszDir, &statbuf) < 0)
	{
		LogAppend(NAMESPACE_BILLING40_LOG FATAL_LEVEL,
			"dir %s does not exist, create it first",
			cszDir);
		return -1;
	}
	if(!S_ISDIR(statbuf.st_mode))
	{
		LogAppend(NAMESPACE_BILLING40_LOG FATAL_LEVEL,
			"%s is configed as a dir, but it is not a dir",
			cszDir);
		return -1;
	}
	return 0;
}

//int32 NAMESPACE_BILLING40_FRAME CProcessMgr::mkdir(char *szDir) const
//{
//	if(szDir==NULL) return -1;
//	if(*szDir=='\0') return 0;
//	while(*szDir=='/') ++szDir;
//	char *szPos = strchr(szDir, '/');
//	char cLastChar;
//	if(szPos==NULL)
//	{
//		cLastChar = '\0';
//	}
//	else
//	{
//		cLastChar = '/';
//		szPos = '\0';
//	}
//	int32 iRet = 0;
//	{
//		struct stat statbuf;
//		iRet = stat(szDir, &statbuf);
//	}
//	if(iRet<0)
//	{
//		iRet = ::mkdir(szDir, S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH);
//		if(iRet!=0)
//		{
//			LogAppend("system",
//				WARN_LEVEL,
//				"create log path %s failed, errno:%d",
//				szDir,
//				errno);
//			return -1;
//		}
//	}
//	*szPos = cLastChar;
//	return mkdir(szPos);
//}
int32 NAMESPACE_BILLING40_FRAME CProcessMgr::redirect_stdio()
{
	char szBuf[512];
	strcpy(szBuf, "/dev/null");
	::close(0);
	int32 iRet = open(szBuf, O_RDONLY);
	if(iRet<0)
	{
		LogAppend(NAMESPACE_BILLING40_LOG FATAL_LEVEL,
			"open %s error, errno:%d",
			szBuf,
			errno);
		return -1;
	}
	sprintf(szBuf,
		"%s/std_out_%d.txt",
		m_objConfig.m_objCommonConfig.m_objLog.m_szPath,
		m_objConfig.m_objCommonConfig.m_iProcId);
	::close(1);
	iRet = open(szBuf, O_WRONLY|O_CREAT);
	if(iRet<0)
	{
		LogAppend(NAMESPACE_BILLING40_LOG FATAL_LEVEL,
			"open %s error, errno:%d",
			szBuf,
			errno);
		return -1;
	}
	sprintf(szBuf,
		"%s/std_error_%d.txt",
		m_objConfig.m_objCommonConfig.m_objLog.m_szPath,
		m_objConfig.m_objCommonConfig.m_iProcId);
	::close(2);
	iRet = open(szBuf, O_WRONLY|O_CREAT);
	if(iRet<0)
	{
		LogAppend(NAMESPACE_BILLING40_LOG FATAL_LEVEL,
			"open %s error, errno:%d",
			szBuf,
			errno);
		return -1;
	}
	return 0;
}

void NAMESPACE_BILLING40_FRAME CProcessMgr::remove_pidFile()
{
	char szHostName[128];
	gethostname(szHostName, 128);

	char szFile[1024];
	sprintf(szFile,
		"%s/pid_%d_%s",
		m_objConfig.m_objCommonConfig.m_objLog.m_szPath,
		m_objConfig.m_objCommonConfig.m_iProcId,
		szHostName);
	int32 iRet = remove(szFile);
	if(iRet!=0)
	{
		LogAppend(NAMESPACE_BILLING40_LOG WARN_LEVEL,
			"remove file :%s error, errno:%d, remove it manually",
			szFile,
			errno);
	}
}

void NAMESPACE_BILLING40_FRAME CProcessMgr::LogAppend(
	const NAMESPACE_BILLING40_LOG LOG_LEVEL& eLevel,
	const char *cszFormat,
	...)
{
	if(m_pLog==NULL) return;
        va_list ap; 
        va_start(ap, cszFormat);
        m_pLog->VLogAppend(
                g_pTime->m_szDateTimeMs,
                g_pTime->m_iYYYYMMDD,
                "system",
                m_tid,
                eLevel,
                cszFormat,
                ap);

        va_end(ap);
}

void NAMESPACE_BILLING40_FRAME CProcessMgr::LogAppend(
	NAMESPACE_BILLING40_LOG CLog *pLog,
	const char *cszModuleName,
	const NAMESPACE_BILLING40_LOG LOG_LEVEL& eLevel,
	const char *cszFormat,
	va_list ap)
{
        pLog->VLogAppend(
                g_pTime->m_szDateTimeMs,
                g_pTime->m_iYYYYMMDD,
                cszModuleName,
                m_tid,
                eLevel,
                cszFormat,
                ap);
}

NAMESPACE_BILLING40_FRAME CProcessMgr::CProcessMgr()
 : m_pObjControl(NULL),
   m_objSysFlow(-1),
   m_iSendLogLevel(NAMESPACE_BILLING40_LOG FATAL_LEVEL),
   m_tSleepTime(MAX_SLEEP_TIME),
   m_lLastManageTime(0L)
{
	strcpy(m_objSysFlow.m_szFlowName, "system");
}

NAMESPACE_BILLING40_FRAME CProcessMgr::~CProcessMgr()
{
}

NAMESPACE_BILLING40_FRAME CProcessMgr::CProcessMgr(const CProcessMgr& rh)
 : m_objSysFlow(-1)
{ }

NAMESPACE_BILLING40_FRAME CProcessMgr&
NAMESPACE_BILLING40_FRAME CProcessMgr::operator=(const CProcessMgr& rh)
{
	return *this;
}

/*******
int32 NAMESPACE_BILLING40_FRAME control(const CControlPkg& controlPkg)
{
	return g_pProcessMgr->control(controlPkg);
}
*******/

int32 NAMESPACE_BILLING40_FRAME CProcessMgr::set_daemon()
{
	int iRet = 0;

	iRet = fork();
	if(iRet<0)
	{
		LogAppend(NAMESPACE_BILLING40_LOG FATAL_LEVEL,
			"set process to daemon error when first fork");
		return -1;
	}
	else if(iRet!=0)
	{
		exit(0);
	}

	iRet=setsid();
	if(iRet<0)
	{
		LogAppend(NAMESPACE_BILLING40_LOG FATAL_LEVEL,
			"set process to daemon error when setsid");
		return -1;
	}

	struct sigaction act;
	act.sa_handler=SIG_IGN;
	sigemptyset(&act.sa_mask);
	act.sa_flags=0;
	sigaction(SIGHUP, &act, NULL);

	iRet=fork();
	if(iRet<0)
	{
		LogAppend(NAMESPACE_BILLING40_LOG FATAL_LEVEL,
			"set process to daemon error when second fork");
		return -1;
	}
	else if(iRet!=0)
		exit(0);

	//chdir("/");
	umask(0);
	setpgrp();

	close(0);
	open("/dev/null", O_RDWR);
	dup2(0, 1);
	dup2(0, 2);
	return 0;
}

